import RecordRTC from 'recordrtc'

class AudioRecorder {
  private recorder: any = null
  private stream: MediaStream | null = null
  private isPaused: boolean = false

  // ✅ 1. 获取设备列表（保持原样）
  async getAudioDevices() {
    const devices = await navigator.mediaDevices.enumerateDevices()
    return {
      inputs: devices.filter((d) => d.kind === 'audioinput'),
      outputs: this.deduplication(devices.filter((d) => d.kind === 'audiooutput'))
    }
  }

  // ✅ 2. 设备去重（保持原样）
  private deduplication(arr: MediaDeviceInfo[]) {
    return arr.filter((item, index) => arr.findIndex((i) => i.groupId === item.groupId) === index)
  }
  async getDefaultMicrophone(index = 0) {
    const { inputs } = await this.getAudioDevices()
    return inputs[index] || null
  }
  //✅ 暂停录音
  async pauseRecording() {
    if (this.recorder && !this.isPaused) {
      this.recorder.pauseRecording()
      this.isPaused = true

      // 暂停音频流的所有轨道
      if (this.stream) {
        this.stream.getTracks().forEach((track) => (track.enabled = false))
      }
    }
  }
  // ✅ 新增恢复录音方法
  async resumeRecording() {
    if (this.recorder && this.isPaused) {
      this.recorder.resumeRecording()
      this.isPaused = false

      // 恢复音频流的所有轨道
      if (this.stream) {
        this.stream.getTracks().forEach((track) => (track.enabled = true))
      }
    }
  }

  // ✅ 3. 开始录音（简化版，确保能录到声音）
  async startRecording(deviceId?: string) {
    await this.stopRecording()

    this.stream = await navigator.mediaDevices.getUserMedia({
      audio: {
        deviceId: deviceId ? { ideal: deviceId } : undefined,
        sampleRate: 44100,
        channelCount: 1
      }
    })

    this.recorder = new RecordRTC(this.stream, {
      type: 'audio',
      mimeType: 'audio/wav',
      sampleRate: 44100,
      numberOfAudioChannels: 1
    })

    this.recorder.startRecording()
  }

  // ✅ 4. 停止录音（使用修复的WAV编码器）
  async stopRecording() {
    return new Promise((resolve) => {
      if (!this.recorder) {
        this.cleanup()
        resolve(null)
        return
      }

      // 确保录音状态是恢复的
      if (this.isPaused) {
        this.resumeRecording()
      }

      this.recorder.stopRecording(() => {
        const blob = this.recorder.getBlob()
        this.fixWAVAudio(blob)
          .then((fixedBlob) => {
            this.cleanup()
            resolve(fixedBlob)
          })
          .catch(() => {
            this.cleanup()
            resolve(blob)
          })
      })
    })
  }

  // ✅ 5. 专业WAV编码器（完整实现 - 修复无人声问题）
  private async fixWAVAudio(blob: Blob): Promise<Blob> {
    return new Promise(async (resolve) => {
      try {
        const arrayBuffer = await blob.arrayBuffer()
        const audioContext = new AudioContext()
        const audioBuffer = await audioContext.decodeAudioData(arrayBuffer)

        // WAV文件参数
        const sampleRate = audioBuffer.sampleRate
        const length = audioBuffer.length
        const numberOfChannels = audioBuffer.numberOfChannels
        const bytesPerSample = 2
        const blockAlign = numberOfChannels * bytesPerSample
        const byteRate = sampleRate * blockAlign
        const dataSize = length * blockAlign
        const fileSize = 36 + dataSize

        // 创建WAV文件头
        const header = new ArrayBuffer(44)
        const view = new DataView(header)

        // RIFF chunk
        this.writeString(view, 0, 'RIFF')
        view.setUint32(4, fileSize, true)
        this.writeString(view, 8, 'WAVE')

        // fmt chunk
        this.writeString(view, 12, 'fmt ')
        view.setUint32(16, 16, true) // PCM格式长度
        view.setUint16(20, 1, true) // PCM格式代码
        view.setUint16(22, numberOfChannels, true)
        view.setUint32(24, sampleRate, true)
        view.setUint32(28, byteRate, true)
        view.setUint16(32, blockAlign, true)
        view.setUint16(34, bytesPerSample * 8, true)

        // data chunk
        this.writeString(view, 36, 'data')
        view.setUint32(40, dataSize, true)

        // 合并PCM数据
        const pcmData = this.floatTo16BitPCM(audioBuffer)
        const wavData = new Uint8Array(header.byteLength + pcmData.length)
        wavData.set(new Uint8Array(header), 0)
        wavData.set(pcmData, 44)

        resolve(new Blob([wavData], { type: 'audio/wav' }))
      } catch (error) {
        console.error('WAV编码失败:', error)
        resolve(blob)
      }
    })
  }

  // ✅ 6. 浮点数转16位PCM（关键函数）
  private floatTo16BitPCM(buffer: AudioBuffer): Uint8Array {
    const length = buffer.length
    const channels = buffer.numberOfChannels
    const result = new Uint8Array(length * channels * 2)
    let offset = 0

    for (let i = 0; i < length; i++) {
      for (let channel = 0; channel < channels; channel++) {
        const sample = Math.max(-1, Math.min(1, buffer.getChannelData(channel)[i]))
        const int16 = sample < 0 ? sample * 32768 : sample * 32767
        result[offset++] = int16 & 0xff
        result[offset++] = (int16 >> 8) & 0xff
      }
    }
    return result
  }

  // ✅ 7. 写入字符串到DataView
  private writeString(view: DataView, offset: number, string: string) {
    for (let i = 0; i < string.length; i++) {
      view.setUint8(offset + i, string.charCodeAt(i))
    }
  }

  // ✅ 8. 清理资源
  private cleanup() {
    if (this.stream) {
      this.stream.getTracks().forEach((track) => track.stop())
      this.stream = null
    }
    if (this.recorder) {
      this.recorder.destroy()
      this.recorder = null
    }
  }
}

export default new AudioRecorder()
